package cn.itcast.ssh.web.action;

import cn.itcast.ssh.domain.Employee;
import cn.itcast.ssh.domain.LeaveBill;
import cn.itcast.ssh.service.ILeaveBillService;
import cn.itcast.ssh.service.IWorkflowService;
import cn.itcast.ssh.utils.SessionContext;
import cn.itcast.ssh.utils.ValueContext;
import cn.itcast.ssh.web.form.WorkflowBean;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;

import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

@SuppressWarnings("serial")
public class WorkflowAction extends ActionSupport implements ModelDriven<WorkflowBean> {

	private WorkflowBean workflowBean = new WorkflowBean();
	
	@Override
	public WorkflowBean getModel() {
		return workflowBean;
	}
	
	private IWorkflowService workflowService;
	
	private ILeaveBillService leaveBillService;

	public void setLeaveBillService(ILeaveBillService leaveBillService) {
		this.leaveBillService = leaveBillService;
	}

	public void setWorkflowService(IWorkflowService workflowService) {
		this.workflowService = workflowService;
	}

	/**
	 * 部署管理首页显示
	 * @return
	 */
	public String deployHome(){
		//1.查询部署对象信息,对应表act_re_deployment
		List<Deployment> depList = workflowService.findDeploymentList();
		//2.查询流程定义信息
		List<ProcessDefinition> pdList = workflowService.findProcessDefinitionList();
		//3.放置到上下文对象中
		ValueContext.putValueContext("depList", depList);
		ValueContext.putValueContext("pdList", pdList);
		return "deployHome";
	}
	
	/**
	 * 发布流程
	 * <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
	   <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
	   <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
	   <tx:method name="*" read-only="true" />
	 * @return
	 */
	public String newdeploy(){
		//获取页面传递的值
		//1.获取页面传递的zip格式的文件,格式是file类型
		File file = workflowBean.getFile();
		//文件名称
		String filename = workflowBean.getFilename();
		//事务管理中,只有save,delete,update才不是只读,所以采用save开头的方法
		workflowService.saveNewDeploye(file,filename);
		System.out.println("完成部署...");
		return "list";
	}
	
	/**
	 * 删除部署信息
	 */
	public String delDeployment(){
		//1.获取部署对象ID
		String deploymentId = workflowBean.getDeploymentId();
		//2.使用部署对象ID,删除流程定义
		workflowService.deleteProcessDefinitionByDeploymentId(deploymentId);
		return "list";
	}
	
	/**
	 * 查看流程图
	 * @throws IOException 
	 */
	public String viewImage() throws IOException{
		//1.获取页面传递的部署对象ID和资源图片名称
		String deploymentId = workflowBean.getDeploymentId();
		//资源图片名称
		String imageName = workflowBean.getImageName();
		//2.获取资源文件表(act_ge_bytearray)中的资源图片输入流inputStream
		InputStream in = workflowService.findImageInputStream(deploymentId,imageName);
		//3.从response获取输出流
		ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();
		//将输入流写入到输出流中
		for(int b = -1 ; (b = in.read()) != -1;) {
			out.write(b);
		}
		out.close();
		in.close();
		return null;//因为输出流已经有内容了,所以不需要使用return了,直接return null即可
	}
	
	// 启动流程
	public String startProcess(){
		//更新请假状态,启动流程实例,让启动的流程实例关联业务
		workflowService.saveStartProcess(workflowBean);
		return "listTask";
	}
	
	
	
	/**
	 * 任务管理首页显示
	 * @return
	 */
	public String listTask(){
		//获取当前用户
		Employee employee = SessionContext.get();
		//获取任务执行人名称
		String name = employee.getName();
		//获取当前执行的任务
		List<Task> list = workflowService.findTaskListByName(name);
		ValueContext.putValueContext("list", list);
		return "task";
	}
	
	/**
	 * 打开任务表单
	 */
	public String viewTaskForm(){
		//任务ID
		String taskId = workflowBean.getTaskId();
		//获取任务表单中任务节点的url连接
		String url = workflowService.findTaskFormKeyByTaskId(taskId);
		//携带任务ID(重定向之后所有参数要重新携带)
		url += "?taskId="+taskId;
		ValueContext.putValueContext("url", url);//根据xml中的写法,直接重定向到url的路径
		return "viewTaskForm";
	}
	
	// 准备表单数据
	public String audit(){
		//1.获取任务ID
		String taskId = workflowBean.getTaskId();
		/*一.使用任务ID,查找请假单ID,从而获取请假单信息*/
		LeaveBill leaveBill = workflowService.findLeaveBillByTaskId(taskId);
		//压入栈顶
		ValueContext.putValueStack(leaveBill);
		/*二.已经任务ID,查询processDefinitionEntity对象,从而获取当前任务完成之后的连线sequenceFlow名称,并防止到List<String> 集合中*/
		List<String> outcomeList = workflowService.findOutcomeListByTaskId(taskId);
		//每个任务节点的连线都在页面罗列出去,如果只有单一连线,并且没有名字,则页面显示的是"默认提交",如果有连线名称,则显示连线的名称
		ValueContext.putValueContext("outcomeList", outcomeList);
		/*三.查询所有历史审核人信息,帮助当前审核人完成审核*/
		List<Comment> commentList = workflowService.findCommentByTaskId(taskId);
		ValueContext.putValueContext("commentList", commentList);
		return "taskForm";
	}
	
	/**
	 * 提交任务
	 */
	public String submitTask(){
		String endProcess = workflowBean.getEndProcess();
		if("终止流程".equals(endProcess)) {
			try {
				workflowService.endProcess(workflowBean);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else {
			workflowService.saveSubmitTask(workflowBean);
		}
		return "listTask";
	}
	
	/**
	 * 查看当前流程图（查看当前活动节点，并使用红色的框标注）
	 */
	public String viewCurrentImage(){
		//任务ID
		String taskId = workflowBean.getTaskId();
		/**一查看流程图*/
		//1.获取任务ID,获取任务对象,使用任务对象获取流程定义ID,查询流程定义对象
		ProcessDefinition pd = workflowService.findProcessDefinitionByTaskId(taskId);
		ValueContext.putValueContext("deploymentId", pd.getDeploymentId());
		ValueContext.putValueContext("imageName", pd.getDiagramResourceName());
		
		/**二查看当前活动任务,获取当前活动对应的x,y,width和height,将4个值放入到Map<String,Object>中*/
		Map<String,Object> map = workflowService.findCoordingByTask(taskId);
		ValueContext.putValueContext("acs", map);
		return "image";
	}
	
	// 查看历史的批注信息
	public String viewHisComment(){
		//获取请假单ID
		Long id = workflowBean.getId();
		//1.使用请假单ID,查询请假单对象,将对象放置栈顶,支持表单回显
		LeaveBill leaveBill = leaveBillService.findLeaveBillById(id);
		ValueContext.putValueStack(leaveBill);
		
		//2.使用请假单ID,查询历史批注信息
		List<Comment> commentList = workflowService.findCommentByLeaveBillId(id);
		ValueContext.putValueContext("commentList", commentList);
		return "viewHisComment";
	}
}
